package org.vacoor.xqq.ui.comp.tree;


/**
 * 去除缩进线, 对节点大小不同的节点动态调整大小
 * @author Vacoor
 */

import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.AbstractLayoutCache;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import javax.swing.tree.VariableHeightLayoutCache;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

public class CategoryTreeUI extends BasicTreeUI {

    public static ComponentUI createUI(JComponent c) {
        return new CategoryTreeUI();
    }

    /**
     * 安装样式
     */
    @Override
    protected void installDefaults() {
        // 去掉基准线
        UIManager.put("Tree.paintLines", false);
        UIManager.put("Tree.lineTypeDashed", false);
        // 设置垂直基准线左侧缩进和右侧缩进
        UIManager.put("Tree.leftChildIndent", 0);
        UIManager.put("Tree.rightChildIndent", 0);
        // 图标
        UIManager.put("Tree.collapsedIcon", null);
        UIManager.put("Tree.expandedIcon", null);
//        UIManager.put("Tree.timeFactor", 100L);

        super.installDefaults();
    }

    /**
     * 安装监听
     */
    @Override
    protected void installListeners() {
        tree.addTreeSelectionListener(new TreeSelectionListener() {
            @Override
            public void valueChanged(final TreeSelectionEvent e) {
                final JTree tree = (JTree) e.getSource();

                TreePath oldPath = e.getOldLeadSelectionPath();
                TreePath newPath = e.getNewLeadSelectionPath();

                // 通知缓存的Size信息已经过期, invalidateSizes() 会更新所有 TreePath
                treeState.invalidatePathBounds(oldPath);
                treeState.invalidatePathBounds(newPath);
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        tree.repaint();
                    }
                });

                // oldtree.repaint();  // 不知道 repaint() 和 nodeChanged() 哪个效率高
                /*- 这种方式效率要低
                DefaultTreeModel model = (DefaultTreeModel) oldtree.getModel();
                if (model == null) {
                    return;
                }
                if (oldPath != null) {
                    model.nodeChanged((TreeNode) oldPath.getLastPathComponent());
                }
                if (newPath != null) {
                    model.nodeChanged((TreeNode) newPath.getLastPathComponent());
                }
                */
            }
        });

        tree.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                if (tree == null) {
                    return;
                }
                tree.repaint();
            }
        });
        super.installListeners();

    }

    @Override
    protected TreeCellRenderer createDefaultCellRenderer() {
        return new CategoryTreeCellRenderer();
    }

    //负责处理大小和展开问题的对象, 某些情况下可重写, 具体查看API
    @Override
    protected AbstractLayoutCache createLayoutCache() {
        // 创建一个可变高布局缓存
        return new VariableHeightLayoutCache();
    }
}
